# Usage: semgrep scan -f semgrep.yml
rules:
- id: "0"
  message: "http requests made without *fiber.Ctx"
  languages: [go]
  severity: WARNING
  patterns:
  - pattern-either:
    - pattern: |
        http.UnwrapWebAPIRequest(...)
    - pattern: |
        http.WebAPIRequest(...)
  - pattern-not-inside: |
      func $FUNC(c *http.Request, ...) $RET {
        ...
      }
# note: the below two rules autofix have slight problems. where `http` is sometimes "net/http". need minor manual tweaking after --autofix.
- id: "1a"
  message: "find http requests made to Pixiv"
  languages: [go]
  severity: INFO
  patterns:
  - pattern: |
      http.UnwrapWebAPIRequest($A, $B)
  fix: |
    http.UnwrapWebAPIRequest(c.Context(), $A, $B)
- id: "1b"
  message: "find http requests made to Pixiv"
  languages: [go]
  severity: INFO
  patterns:
  - pattern: |
      http.WebAPIRequest($A, $B)
  fix: |
    http.WebAPIRequest(c.Context(), $A, $B)
- id: "2"
  message: "gjson.Get without gjson.Valid"
  languages: [go]
  severity: ERROR
  patterns:
  # - pattern-inside: |
  #     func $FUNC(...) $RET {
  #       ...
  #     }
  - pattern: |
      gjson.Get($X, ...)
  - pattern-not-inside: |
      if !gjson.Valid($X) {
        $...DISCARD
      }
      ...
- id: "3"
  message: "http request without context"
  languages: [go]
  severity: WARNING
  # severity: INVENTORY
  patterns:
  - pattern: |
      $REQ, $ERR := http.NewRequestWithContext($...ARGV)
      if $ERR != nil {
        $...I
      }
      $REQ = $REQ.WithContext($CTX)
  fix: |
      $REQ, err := http.NewRequestWithContext($...ARGV)
      if err != nil {
        $...I
      }
- id: "3a"
  message: "http request without context"
  languages: [go]
  severity: WARNING
  # severity: INVENTORY
  patterns:
  - pattern: |
      http.NewRequest($...ARGV)
  fix: |
      http.NewRequestWithContext(r.Context(), $...ARGV)
- id: "4"
  message: "fmt.Sprint on string"
  languages: [go]
  severity: WARNING
  pattern: |
    fmt.Sprint(($S : string))
- id: "5"
  message: "unhandled error"
  languages: [go]
  severity: WARNING
  pattern: |
    (_ : error) = ...
- id: "6"
  message: "raw UserArtCategory string"
  languages: [go]
  severity: WARNING
  patterns:
  - pattern: |
      ($A : UserArtCategory) == $B
  - pattern-not: |
      ($A : UserArtCategory) == ($B : UserArtCategory)
- id: "7"
  message: "c.Render"
  languages: [go]
  severity: INFO
  pattern: |
    c.Render("$NAME", fiber.Map{$...INSIDE})
  paths:
    exclude:
      - "render_types.go"
  fix: |
    Render(w, r, Data_$NAME{$...INSIDE})
- id: "8"
  message: "c.Render"
  languages: [go]
  severity: INFO
  patterns:
  - pattern-inside: |
      c.Render(...)
  - pattern: |
      fiber.Map { $...BEFORE, "$A": $B, $...AFTER }
  fix: |
    fiber.Map { $...BEFORE, $A: $B, $...AFTER }
  paths:
    exclude:
      - "render.go"
- id: "9"
  message: "still using *fiber.Ctx"
  languages: [go]
  severity: INVENTORY
  patterns:
  - pattern: |
      func $NAME(c *fiber.Ctx) error {
        $...I
      }
  fix: |
    func $NAME(w http.ResponseWriter, r *http.Request) error {
      $...I
    }
- id: "10"
  message: "masquerading CompatRequest"
  languages: [go]
  severity: INFO
  patterns:
  - pattern: |
      $FUNC((r : *http.Request))
  # fix: |
  #   func $NAME(w http.ResponseWriter, r *http.Request) error {
  #     $...I
  #   }
- id: "11"
  message: "Use StatusSeeOther or StatusPermanentRedirect"
  languages: [go]
  severity: WARNING
  patterns:
  - pattern: |
      StatusFound
- id: "12"
  message: "response body not closed"
  comment: "Needed to reuse connections"
  languages: [go]
  severity: ERROR
  patterns:
  - pattern: |
      ($RESP : *http.Response), $ERR := ...
  - pattern-not-inside: |
      ...
      defer $RESP.Body.Close()
- id: "13a"
  message: "untranslated errors.New"
  languages: [go]
  severity: ERROR
  pattern: |
    errors.New("$MSG")
  fix: |
    i18n.Error("$MSG")
- id: "13b"
  message: "untranslated fmt.Errorf"
  languages: [go]
  severity: ERROR
  pattern: |
    fmt.Errorf("$MSG", $...ARGS)
  fix: |
    i18n.Errorf("$MSG", $...ARGS)
- id: "14"
  message: "non-global regexp.MustCompile"
  languages: [go]
  severity: ERROR
  patterns:
  - pattern-inside: |
      {
        ...
      }
  - pattern: |
      $VAR := regexp.MustCompile($PATT)
  fix: |
      var $VAR = regexp.MustCompile($PATT)
- id: "15"
  message: "http.DefaultClient"
  languages: [go]
  severity: ERROR
  pattern: |
    http.DefaultClient
  fix: |
    utils.HttpClient
